using System.Linq;
using System.Reflection;
using System.Web.Mvc;
using Dyn.News.Extensions;
using Dyn.News.Models;
using Dyn.News.Routing;
using Dyn.News.Services;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Aspects;
using Orchard.Core.Routable.Services;
using Orchard.Data;
using Orchard.DisplayManagement;
using Orchard.Localization;
using Orchard.UI.Admin;
using Orchard.UI.Navigation;
using Orchard.UI.Notify;
using Orchard.Settings;
using Orchard;
using System.Collections.Generic;
using Orchard.Core.Contents.ViewModels;
using System;

namespace Dyn.News.Controllers {

    [ValidateInput(false), Admin]
    public class CategoryAdminController : Controller, IUpdateModel {
        private readonly ICategoryervice _Categoryervice;
        private readonly IArticleService _ArticleService;
        private readonly IContentManager _contentManager;
        private readonly ITransactionManager _transactionManager;
        private readonly ICategoryPathConstraint _categoryPathConstraint;
        private readonly ISiteService _siteService;

        public CategoryAdminController(
            IOrchardServices services,
            ICategoryervice Categoryervice,
            IArticleService ArticleService,
            IContentManager contentManager,
            ITransactionManager transactionManager,
            ICategoryPathConstraint categoryPathConstraint,
            ISiteService siteService,
            IShapeFactory shapeFactory) {
            Services = services;
            _Categoryervice = Categoryervice;
            _ArticleService = ArticleService;
            _contentManager = contentManager;
            _transactionManager = transactionManager;
            _categoryPathConstraint = categoryPathConstraint;
            _siteService = siteService;
            T = NullLocalizer.Instance;
            Shape = shapeFactory;
        }

        dynamic Shape { get; set; }
        public Localizer T { get; set; }
        public IOrchardServices Services { get; set; }

        public ActionResult Create() {
            if (!Services.Authorizer.Authorize(Permissions.ManageCategory, T("Not allowed to create Category")))
                return new HttpUnauthorizedResult();

            NewsCategoryPart Category = Services.ContentManager.New<NewsCategoryPart>(typeof(NewsCategoryPart).Name);
            if (Category == null)
                return HttpNotFound();
            Category.CategoryParents = Services.ContentManager.Query<NewsCategoryPart, NewsCategoryPartRecord>().Where(p => p.ParentID == Utils.ParentID).List();
            dynamic model = Services.ContentManager.BuildEditor(Category);
            // Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
            return View((object)model);
        }

        [HttpPost, ActionName("Create")]
        public ActionResult CreatePOST() {
            if (!Services.Authorizer.Authorize(Permissions.ManageCategory, T("Couldn't create category")))
                return new HttpUnauthorizedResult();

            var Category = Services.ContentManager.New<NewsCategoryPart>(typeof(NewsCategoryPart).Name);

            _contentManager.Create(Category, VersionOptions.Draft);
            dynamic model = _contentManager.UpdateEditor(Category, this);
            try{
                int parent = Convert.ToInt32(ModelState["ParentID"]);
            }
            catch
            {
            ModelState.Remove("ParentID");
            ModelState.Add("ParentID", new ModelState());
                ModelState.SetModelValue("ParentID",new ValueProviderResult(0,"0",null));
            }
                if (!ModelState.IsValid) {
                _transactionManager.Cancel();
                // Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
                return View((object)model);
            }

            _contentManager.Publish(Category.ContentItem);
            _categoryPathConstraint.AddPath(Category.As<IRoutableAspect>().Path);

            return Redirect(Url.CategoryForAdmin(Category));
        }

        public ActionResult Edit(int categoryID) {
            if (!Services.Authorizer.Authorize(Permissions.ManageCategory, T("Not allowed to edit category")))
                return new HttpUnauthorizedResult();
            NewsCategoryPart Category = Services.ContentManager.Query<NewsCategoryPart, NewsCategoryPartRecord>().List().Single(p=>p.Id == categoryID);
            if (Category == null)
                return HttpNotFound();
            //List<NewsCategoryPart> aaa = new List<NewsCategoryPart>();
            //NewsCategoryPart root = new NewsCategoryPart();
            //root.ParentID = 0;
            //root.Name = "Root";
            //aaa.Add(root);
            Category.CategoryParents = Services.ContentManager.Query<NewsCategoryPart, NewsCategoryPartRecord>().Where(p => p.ParentID == Utils.ParentID).List();
            dynamic model = Services.ContentManager.BuildEditor(Category);
            // Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
            return View((object)model);
            //var Category = _Categoryervice.Get(categoryID, VersionOptions.Latest);
            //if (Category == null)
            //    return HttpNotFound();
            // //= Services.ContentManager.Query<NewsCategoryPart, CategoryPartRecord>().Where(p => p.ParentID == Utils.ParentID).List();
            //dynamic model = Services.ContentManager.BuildEditor(Category);
            //// Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
            //return View((object)model);
        }

        [HttpPost, ActionName("Edit")]
        [FormValueRequired("submit.Delete")]
        public ActionResult EditDeletePOST(int categoryID) {
            if (!Services.Authorizer.Authorize(Permissions.ManageCategory, T("Couldn't delete category")))
                return new HttpUnauthorizedResult();

            var Category = _Categoryervice.Get(categoryID, VersionOptions.DraftRequired);
            if (Category == null)
                return HttpNotFound();
            _Categoryervice.Delete(Category);

            Services.Notifier.Information(T("Category deleted"));

            return Redirect(Url.CategoryForAdmin());
        }
        [HttpPost, ActionName("Edit")]
        [FormValueRequired("submit.Filter")]
        public ActionResult EditFilterPOST(int categoryID)
        {
            if (!Services.Authorizer.Authorize(Permissions.ManageCategory, T("Couldn't View category")))
                return new HttpUnauthorizedResult();

            var Category = _Categoryervice.Get(categoryID, VersionOptions.DraftRequired);
            if (Category == null)
                return HttpNotFound();
            _Categoryervice.Delete(Category);

            Services.Notifier.Information(T("Category deleted"));

            return Redirect(Url.CategoryForAdmin());
        }

        [HttpPost, ActionName("Edit")]
        [FormValueRequired("submit.Save")]
        public ActionResult EditPOST(int categoryID) {
            if (!Services.Authorizer.Authorize(Permissions.ManageCategory, T("Couldn't edit category")))
                return new HttpUnauthorizedResult();

            var Category = _Categoryervice.Get(categoryID, VersionOptions.DraftRequired);
            if (Category == null)
                return HttpNotFound();

            dynamic model = Services.ContentManager.UpdateEditor(Category, this);
            if (!ModelState.IsValid) {
                Services.TransactionManager.Cancel();
                // Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
                return View((object)model);
            }

            _contentManager.Publish(Category);
            _categoryPathConstraint.AddPath(Category.As<IRoutableAspect>().Path);
            Services.Notifier.Information(T("Category information updated"));

            return Redirect(Url.CategoryForAdmin());
        }

        [HttpPost]
        public ActionResult Remove(int categoryID) {
            if (!Services.Authorizer.Authorize(Permissions.ManageCategory, T("Couldn't delete category")))
                return new HttpUnauthorizedResult();

            var Category = _Categoryervice.Get(categoryID, VersionOptions.Latest);

            if (Category == null)
                return HttpNotFound();

            _Categoryervice.Delete(Category);

            Services.Notifier.Information(T("Category was successfully deleted"));
            return Redirect(Url.CategoryForAdmin());
        }

        public ActionResult List() {
            var list = Services.New.List();
            list.AddRange(_Categoryervice.Get(VersionOptions.Latest)
                              .Select(b => {
                                          var Category = Services.ContentManager.BuildDisplay(b, "SummaryAdmin");
                                          Category.TotalPostCount = _ArticleService.Get(b, VersionOptions.Latest).Count();
                                          return Category;
                                      }));

            dynamic viewModel = Services.New.ViewModel()
                .ContentItems(list);
            ViewBag.CategoryParents = Services.ContentManager.Query<NewsCategoryPart, NewsCategoryPartRecord>().List().Where(p => p.ParentID == Utils.ParentID).ToList();
            // Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
            return View((object)viewModel);
        }

        public ActionResult Item(int categoryID, PagerParameters pagerParameters) {
            Pager pager = new Pager(_siteService.GetSiteSettings(), pagerParameters);
            NewsCategoryPart CategoryPart = _Categoryervice.Get(categoryID, VersionOptions.Latest).As<NewsCategoryPart>();

            if (CategoryPart == null)
                return HttpNotFound();

            var Articles = _ArticleService.Get(CategoryPart, pager.GetStartIndex(), pager.PageSize, VersionOptions.Latest)
                .Select(bp => _contentManager.BuildDisplay(bp, "SummaryAdmin"));

            dynamic Category = Services.ContentManager.BuildDisplay(CategoryPart, "DetailAdmin");

            var list = Shape.List();
            list.AddRange(Articles);
            Category.Content.Add(Shape.Parts_Category_Article_ListAdmin(ContentItems: list), "5");

            var totalItemCount = _ArticleService.PostCount(CategoryPart, VersionOptions.Latest);
            Category.Content.Add(Shape.Pager(pager).TotalItemCount(totalItemCount), "Content:after");

            // Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
            return View((object)Category);
        }
        [HttpPost]
        public ActionResult SubList(string select)
        {
            int parent=0;
            try{
                parent = Convert.ToInt32(select);
            }
            catch{
            parent=0;
            }
            var list = Services.New.List();
            list.AddRange(_Categoryervice.Get(VersionOptions.Latest,parent)
                              .Select(b =>
                              {
                                  var Category = Services.ContentManager.BuildDisplay(b, "SummaryAdmin");
                                  Category.TotalPostCount = _ArticleService.Get(b, VersionOptions.Latest).Count();
                                  return Category;
                              }));

            dynamic viewModel = Services.New.ViewModel()
                .ContentItems(list);
            ViewBag.CategoryParents = Services.ContentManager.Query<NewsCategoryPart, NewsCategoryPartRecord>().List().Where(p => p.ParentID == Utils.ParentID).ToList();
            if (parent != 0)
                ViewBag.Parent = _Categoryervice.Get().Single(p => p.Id == parent).Name;
            else
                ViewBag.Parent = "Root";
            
            // Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
            return View((object)viewModel);
        }

        bool IUpdateModel.TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) {
            return TryUpdateModel(model, prefix, includeProperties, excludeProperties);
        }

        void IUpdateModel.AddModelError(string key, LocalizedString errorMessage) {
            ModelState.AddModelError(key, errorMessage.ToString());
        }
    }
}